macro_rules! yoo {
    // 此代码中的expr是表达式
    ($name:expr) => {
        println!("yoo is {}", $name);
    };
}

// 此注解表示宏可以被外部访问
#[macro_export]
macro_rules! add {
    // 支持两个表达式
    ($a:expr, $b:expr) => {
        $a + $b
    };
    // 同样也支持一个表达式
    ($a:expr) => {
        $a
    }
}

#[macro_export]
macro_rules! add_as {
    ($a:expr, $b:expr, $tye:ty) => {
        $a as $tye + $b as $tye
    };
}

#[macro_export]
macro_rules! add_as_one {
    // 接收n个表达式
    // 重复的标记类型包含在$()中，后面跟着一个分隔符和一个*或+，表示该标记将重复的次数。分隔符用于区分不同的标记。$()块后跟*或+用于表示重复的代码块。在上面的例子中，+$a是一个重复的代码。
    ($($a:expr), *) => {
        0 $(+$a)*
    }
}

#[macro_export]
macro_rules! mul_as {
    // 接收n个表达式
    // 重复的标记类型包含在$()中，后面跟着一个分隔符和一个*或+，表示该标记将重复的次数。分隔符用于区分不同的标记。$()块后跟*或+用于表示重复的代码块。在上面的例子中，+$a是一个重复的代码。
    ($($a:expr), +) => { //     ($($a:expr), +) => { 和前面的是一样的效果
        1 $(*$a)*
    }
}

// 如果传递了一个参数，则第一个分支处理这种情况
// 第二个函数处理传递两个参数的情况
// 第三个分支使用其他参数再次调用add宏
#[macro_export]
macro_rules! add_as_two {
    ($a:expr) => {
        $a
    };

    ($a:expr, $b:expr) => {
        $a + $b
    };
    // tt表示一个词法树，此表达式迭代调用
    ($a:expr, $($b:tt)*) => {
        $a + add_as_two!($($b)*)
    }
}


/// item —— 一个项（item），像一个函数，结构体，模块等。
/// block —— 一个块（block）（即一个语句块或一个表达式，由花括号所包围）
/// stmt —— 一个语句（statement）
/// pat —— 一个模式（pattern）
/// expr —— 一个表达式（expression）
/// ty —— 一个类型（type）
/// ident —— 一个标识符（indentfier）
/// path —— 一个路径（path）（例如，foo，::std::mem::replace，transmute::<_, int>，...）
/// meta —— 一个元数据项；位于#[...] 和#![...] 属性
/// tt —— 一个词法树
/// vis —— 一个可能为空的 Visibility 限定词
pub fn print_yoo() {
    yoo!("天天");
}